#ifndef APP_H
#define APP_H

// ###########################################################################################################################################
// MODELO DO RECURSOS DE HARDAWARES
#define MODEL			"hr01"
#define FIRMWARE_VERSION "1.1"
#define PROGAM_NAME "examples " MODEL " firmware v" FIRMWARE_VERSION " [compiled in " __DATE__ " " __TIME__ "]" CMD_TERMINATOR

#define LOG_APP 			pdON
#define LOG_MODBUS_SLAVE	pdOFF
#define LOG_MODBUS_MASTER	pdOFF

// ###########################################################################################################################################
// INCLUDES OBRIGATÓRIAS
#include "_config_cpu_.h"
#include "stdio_uc.h"
#include "systick.h"
#include "delay.h"
#include "led_error.h"
#include "beep.h"
#include "gkey.h"
#include "liquid_crystal.h"

#include "modbus_slave.h"
#include "modbus_master.h"

// ###########################################################################################################################################
// MODBUS
#define rs485_ENTXS_DIR		GPIO0_DIR
#define rs485_ENTXS_ON		GPIO0_SET
#define rs485_ENTXS_OFF 	GPIO0_CLR
#define rs485_ENTXS			BIT_30

#define rs485_ENTXM_DIR		GPIO0_DIR
#define rs485_ENTXM_ON		GPIO0_SET
#define rs485_ENTXM_OFF 	GPIO0_CLR
#define rs485_ENTXM			BIT_17

#define BAUDRATE_RASPBERRY		57600 // Não usar acima de 57600, pois há erro de recepção do raspberry.
									// Deve ser algum bug de hardware do rasp porque o baudrate do rasp não fica indentico do ARM
									// pois a comunicação com PC a 115200 funciona bem.
									// Ou a tolerancia de erro no rasp não é tão grande como no PC onde o ARM tem um erro considerável
									//	TODO Quando usar o oscilador interno do ARM refazer os testes a sabe com usando oscilador interno do ARM isso se resolve

#define BAUDRATE_THERMOMETER 	57600

// ###########################################################################################################################################
// TERMOMETROS
#define nTHERMOMETER  		1		// Quantidade de termômetro que o RH deve gerenciar. O ID modbus do termômetro deve ser sequencial de 1 a quantidade de termômetro

typedef enum {
	cmdNONE = 0,
    cmdGET_INFO,        			// Comando para ler os registradores de informações do termômetro
    cmdGET_TEMPERATURE, 			// Comando para ler os valores de temperatura
    cmdSET_TEMPERATURE_TYPE,		// Comando para configurar todos os termômetros a trabalharem com com graus Celsius ou Graus Fahrenheit
    								//  0 (padrão) = Tratamento da temperatura determinada pelo jumper do termômetro;
									//	1 = Temperatura tratada em graus Celsius;
									//	2 = Temperatura tratada em graus Fahrenheit.
    cmdRST_TEMPERATURE_STATISTIC	// Comando para iniciar as estátiticas de todos os termometros
} tCommand;

typedef struct {
	int stsCom;		// Status de comunicação:
						//		0: Sem comunicação com o dispositivo. O mesmo não está conectado, ou está desligado, ou não há dispositivo no ID em acesso.
						//		1: O termômetro recebeu uma função que não foi implementada;
						//		2: Foi acessado a um endereço de registrador inexistente;
						//		3: Foi tentado gravar um valor inválido no registrador do termômetro;
						//		4: Um irrecuperável erro ocorreu enquanto o termômetro estava tentando executar a ação solicitada;
						//		5: Comunicação estabelecida com sucesso
	u16 sts;		// Status do termômetro
						// bit[4]: Em que grandeza o termômetro está trabalhando:
						//		0: Graus Celsius;
						// 		1: Graus Fahrenheit.
						// bits[3:0]: Status do sensor:
						// 		0: Sinaliza que o termômetro está lendo pela primeira vez o sensor. Isto somente acontece no momento que o termômetro é ligado.
						// 		1: O termômetro já contém o valor convertido;
						// 		2: Sinaliza um erro, indica que o valor está abaixo da escala permitida pelo termômetro;
						// 		3: Sinaliza um erro, indica que o valor está acima da escala permitida pelo termômetro;
	s32 value; 		// Valor em graus, dependo da grandeza selecionada, valor multiplicado por 10
	s32 valueMin;	// Valor mínimo em graus alcançado a partir do reinício da estatística, valor multiplicado por 10
	s32 valueMax;	// Valor máximo em graus alcançado a partir do reinício da estatística, valor multiplicado por 10
	char model[5];
	char firmware[3];
} tThermometer;


// ###########################################################################################################################################
// RELAYS
typedef struct {
	int st; // estado dp rele
	volatile uint timeout; // contagem de tempo em ms para voltar ao estado anterior do rele
} tRelay, *pRelay;

// ###############################################################################
// CONTROL
typedef struct {
	unsigned action:1; 			// Sinaliza que há uma ação sendo feita. Configuração de grandeza de temperatura; reset estatiticas ou o experimento
	unsigned setTempStatics:1; // Sinaliza para emitir comandos de ajustes de grandezas de temperatura nos termômetros
	unsigned setTempType:1;		// Sinaliza para resetar todas as estatisticas de temperatura nos termômetros
	uint tempType;				// Especifica em que grandeza de temperatura os termômetros devem ser configurado
								//		0 (padrão) = Tratamento da temperatura determinada pelo jumper do termômetro
								// 		1 = Configurar todos os termômetros a trabalhar com graus Celsius(0)
								//		2 = Configurar todos os termômetros a trabalhar com graus Fahrenheit(1)
	volatile uint ticks;
	volatile char key;	// Valor do teclado pressionado
	tRelay relay1;
	tRelay relay2;
	tThermometer thermometer[nTHERMOMETER];
} tControl, *pControl;
tControl control;

void breakFloat(s32 value, int* integer, int* digit);
void stringFloat(pchar s, int integer, int digit);
void temp_InitStatistic(void);
void temp_SetType(uint type);

void relay_Init(void);
void relay_Tick(void);
int relay_Set(int rly, int st, uint timeout);

void onKeyDown(char key);
void onKeyPress(char key);
void onKeyUp(char key);

void app_Init(void);
void app_Tick(void);
void app_Process(void);

void modbus_Init(uint id);
void modbus_SendCommand(uint slaveID, tCommand c, u16 value);
void modbus_Tick(void);
void modbus_Process(void);

void prompt_Process(void);

#endif
